package com.rtos.controller;


import com.rtos.model.cpu.CPU;
import com.rtos.model.fileSystem.FileSystem;
import com.rtos.model.process.ProcessDispatcher;
import com.rtos.model.process.processDispatchAlgorithm.AbstractProcessDispatcher;
import com.rtos.vo.dat.DeviceAllocationTableVO;
import com.rtos.vo.file.blockTableView.BlockTableView;

import com.rtos.model.process.Process;
import com.rtos.model.process.ProcessFactory;
import com.rtos.model.process.processDispatchAlgorithm.RoundRobin;
import com.rtos.model.terminal.Terminal;
import com.rtos.vo.file.diskPane.DiskViewer;
import com.rtos.vo.file.filetree.FileTrees;
import com.rtos.vo.memory.MemoryPaneVO;
import com.rtos.vo.process.ProcessQueueVO;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.Pane;

import java.util.ArrayList;
import java.util.concurrent.*;

import com.rtos.model.fileSystem.FileUtil;

/**
 * @Author: Redi
 * @Date: 2021/8/30 18:47
 * @Description:
 */
public class MainController {

    public TreeView FileTree;
    public Pane diskPane;
    public BlockTableView blockViewer;
    public DiskViewer diskViewer;


    //命令行操作
    public TextArea taTerminal;
    public Terminal terminal;


    /**
     * 文件系统
     * CPU
     * 进程调度工具
     * 进程调度算法
     *
     */
    private FileSystem fileSystem = FileSystem.getInstance();
    private CPU cpu = CPU.getInstance();
    private ProcessDispatcher processDispatcher = ProcessDispatcher.getInstance();
    private AbstractProcessDispatcher processScheduler = new RoundRobin();

    private ProcessFactory processFactory = ProcessFactory.getInstance();

    @FXML
    TextArea globalClockTextArea;
    @FXML
    TextArea instructionTextArea;
    @FXML
    TextArea axTextArea;
    @FXML
    TextArea resultTextArea;
    @FXML
    TextArea timeSliceTextArea;

    @FXML
    Button suspendButton;


    /**
     * 运行队列相关GUI
     */
    @FXML
    TableView<Process> runningProcessTableView;
    @FXML
    TableColumn<Process, IntegerProperty> runningPidTableColumn;
    @FXML
    TableColumn<Process, DoubleProperty> runningTotalRunTimeTableColumn;
    @FXML
    TableColumn<Process, DoubleProperty> runningRestRunTimeTableColumn;
    @FXML
    TableColumn<Process, DoubleProperty> runningLastRunTimeTableColumn;
    @FXML
    TableColumn<Process, StringProperty> runningDeviceTypeTableColumn;

    /**
     * 就绪队列相关GUI
     */
    @FXML
    TableView<Process> readyQueueTableView;
    @FXML
    TableColumn<Process, IntegerProperty> readyPidTableColumn;
    @FXML
    TableColumn<Process, StringProperty> readyTotalRunTimeTableColumn;
    @FXML
    TableColumn<Process, StringProperty> readyRestRunTimeTableColumn;
    @FXML
    TableColumn<Process, StringProperty> readyLastRunTimeTableColumn;
    @FXML
    TableColumn<Process, StringProperty> readyDeviceTypeTableColumn;

    /**
     * 阻塞队列相关GUI
     */
    @FXML
    TableView<Process> blockingQueueTableView;
    @FXML
    TableColumn<Process, IntegerProperty> blockingPidTableColumn;
    @FXML
    TableColumn<Process, StringProperty> blockingTotalRunTimeTableColumn;
    @FXML
    TableColumn<Process, StringProperty> blockingRestRunTimeTableColumn;
    @FXML
    TableColumn<Process, StringProperty> blockingLastRunTimeTableColumn;
    @FXML
    TableColumn<Process, StringProperty> blockingDeviceTypeTableColumn;
    @FXML
    TableColumn<Process, IntegerProperty> blockingOccupyTimeTypeTableColumn;

    /**
     * 设备分配表相关GUI
     */
    @FXML
    TableView<DeviceAllocationTableVO> DATTableView;
    @FXML
    TableColumn<DeviceAllocationTableVO, StringProperty> deviceNameTableColumn;
    @FXML
    TableColumn<DeviceAllocationTableVO, StringProperty> occupyProcessTableColumn;
    @FXML
    TableColumn<DeviceAllocationTableVO, StringProperty> deviceWaitingProcessTableColumn;


    @FXML
    Pane memoryPane;


    public static ExecutorService threadPool = new ThreadPoolExecutor(4, 8,
            5, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(10),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());


    public void initialize() throws Exception {

        /**
         * 可拓展多种进程调度算法
         */

        instructionTextArea.textProperty().bind(cpu.instructionProperty());
        axTextArea.textProperty().bind(cpu.axProperty());
        resultTextArea.textProperty().bind(cpu.resultProperty());
        timeSliceTextArea.textProperty().bind(cpu.timeSliceProperty().asString());

        globalClockTextArea.textProperty().bind(cpu.globalTime.asString());
        ProcessQueueVO.setRunningQueueTableView(runningProcessTableView, runningPidTableColumn, runningTotalRunTimeTableColumn
                , runningRestRunTimeTableColumn, runningLastRunTimeTableColumn, runningDeviceTypeTableColumn);
        ProcessQueueVO.setReadyQueueTableView(readyQueueTableView, readyPidTableColumn, readyTotalRunTimeTableColumn
                , readyRestRunTimeTableColumn, readyLastRunTimeTableColumn, readyDeviceTypeTableColumn);
        ProcessQueueVO.setBlockingQueueTableView(blockingQueueTableView, blockingPidTableColumn, blockingTotalRunTimeTableColumn
                , blockingRestRunTimeTableColumn, blockingLastRunTimeTableColumn, blockingDeviceTypeTableColumn, blockingOccupyTimeTypeTableColumn);
        DeviceAllocationTableVO.setDATTableView(DATTableView, deviceNameTableColumn, occupyProcessTableColumn, deviceWaitingProcessTableColumn);

        MemoryPaneVO.setMemoryPane(memoryPane);


        ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(5);

        /**
         * 调整时钟频率 period 刷新率过高会导致 JavaFX Thread UI线程报 NPE
         */
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            if(cpu.isRunning()){
                cpu.time();
            }
        }, 1, 500, TimeUnit.MILLISECONDS);


        threadPool.execute(() -> {

            /**
             * 先上锁再判断 cpu是否运行 再执行操作
             */
            while(true){
                try {
                    CPU.lock.lock();
                    CPU.condition2.await();
                    if(cpu.isRunning()){
                        processScheduler.doDispatch();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    CPU.lock.unlock();
                }
            }

        });

        threadPool.execute(() -> {
            while (true){
                cpu.cpuRun();
            }


        });


        //终端命令行输入
        FileUtil fileUtil = FileUtil.getInstance();
        ArrayList<String> files =  fileUtil.getDirectorys("root");

        this.diskViewer = new DiskViewer(this.diskPane);
        this.diskViewer.setBlockTableView(this.blockViewer);
        this.terminal = new Terminal(this.taTerminal, fileUtil, FileTree,diskViewer);
        FileTrees ft = new FileTrees(FileTree, fileUtil,diskViewer);//左边的文件树
        //左边的磁盘空间和盘块内容


    }

    public void suspendOrRun() {
        if (cpu.isRunning()) {
            suspendButton.textProperty().set("运行");
            cpu.setRunning(false);

        } else if (!cpu.isRunning()) {
            suspendButton.textProperty().set("暂停运行");
            cpu.setRunning(true);

        }
    }

    public void createProcess() {
        processFactory.createProcess();
    }

}
